package net.xumf.service.master.impl;

import net.xumf.dao.master.SystemUserRepository;
import net.xumf.domain.master.SystemPermission;
import net.xumf.domain.master.SystemRole;
import net.xumf.domain.master.SystemUser;
import net.xumf.service.master.SystemPermissionService;
import net.xumf.service.master.SystemRoleService;
import net.xumf.service.master.SystemUserService;
import net.xumf.support.auth.CurrentUser;
import net.xumf.support.auth.VerificationUtil;
import net.xumf.support.common.BaseServiceImpl;
import net.xumf.support.consts.Constants;
import net.xumf.support.converter.PageConverter;
import net.xumf.support.enums.CodeEnum;
import net.xumf.support.enums.UserStatusEnum;
import net.xumf.support.exception.NotFoundDataRowInfoException;
import net.xumf.support.exception.SystemException;
import net.xumf.support.exception.UserLoginException;
import net.xumf.support.model.dto.*;
import net.xumf.support.model.vo.PageVO;
import net.xumf.support.security.PasswordService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
public class SystemUserServiceImpl extends BaseServiceImpl<SystemUserRepository, SystemUser, Long> implements SystemUserService {


    @Autowired
    private SystemRoleService systemRoleService;

    @Autowired
    private SystemPermissionService systemPermissionService;

    @Override
    public <S extends SystemUser> SystemUser add(S pojo) {
        int salt = PasswordService.constructSalt();
        String encryptPassword = PasswordService.encryptPassword(Constants.Normal.DEFAULT_PASSWORD, salt);
        pojo.setPassword(encryptPassword);
        pojo.setSalt(salt);
        return super.add(pojo);
    }

    @Override
    public SystemUser registerUser(SystemUser systemUser) {
        // 加密密码
        int salt = PasswordService.constructSalt();
        String encryptPassword = PasswordService.encryptPassword(systemUser.getPassword(), salt);
        systemUser.setUsername(systemUser.getLoginName());
        systemUser.setSalt(salt);
        systemUser.setPassword(encryptPassword);
        systemUser.setStatus(UserStatusEnum.NORMAL.getCode());
        return repository.save(systemUser);
    }

    @Override
    public SystemUser getByLoginName(String loginName) {
        Optional<SystemUser> userOptional = repository.findByLoginName(loginName);
        return userOptional.orElseThrow(() -> new NotFoundDataRowInfoException(CodeEnum.QUERY_NOT_FOUND_ROW_ERROR));
    }

    @Override
    public PageVO getByUsername(PageDTO dto) {
        Pageable pageable = PageConverter.pageVOToPageable(dto);
        Page<SystemUser> systemUserPage = repository.findByUsername("", pageable);
        return PageConverter.pageToPageDTO(systemUserPage);
    }

    @Override
    public SystemUser login(LoginDTO loginDTO) {
        //添加用户认证信息
        SystemUser user = getByLoginName(loginDTO.getLoginName());
        String encryptPassword = PasswordService.encryptPassword(loginDTO.getPassword(), user.getSalt());
        if (!encryptPassword.equals(user.getPassword())) {
            throw new UserLoginException(CodeEnum.USER_PASS_ERROR);
        }
        CurrentUser.instance().set(user);

        // 获取用户拥有角色
        List<SystemRole> roleList = systemRoleService.getByRoleIdIn(user.getRoles());
        // 获取用户角色code列表
        List<String> roleCodeList = roleList.stream().map(SystemRole::getCode).collect(Collectors.toList());
        // 获取角色中所有的权限id
        List<String> permissionIdsStrings = roleList.stream().map(SystemRole::getPermissions)
                .collect(Collectors.toList());
        // 获取用户拥有所有权限code列表
        List<String> permissionCodeList = systemPermissionService.getByPermissionIdIn(permissionIdsStrings).stream()
                .map(SystemPermission::getCode).collect(Collectors.toList());
        VerificationUtil.getInstance().setRoles(roleCodeList);
        VerificationUtil.getInstance().setPermissions(permissionCodeList);

        return user;
    }

    @Override
    public void passwordChange(PasswordChangeDTO dto) {

        int salt = PasswordService.constructSalt();
        String encryptPassword = PasswordService.encryptPassword(dto.getPassword(), salt);
        SystemUser systemUser = new SystemUser();
        systemUser.setId(dto.getId());
        systemUser.setSalt(salt);
        systemUser.setPassword(encryptPassword);
        this.dynamicSave(systemUser);
    }

    @Override
    public void passwordChangeMine(PasswordChangeMineDTO dto) throws Exception {

        SystemUser user = CurrentUser.instance().get();
        String afterDecryptionPassword = PasswordService.decryptAesPassword(dto.getOldPassword(), Constants.Normal.PASSWORD_KEY);
        String encryptPassword = PasswordService.encryptPassword(afterDecryptionPassword, user.getSalt());
        if (encryptPassword.equals(user.getPassword())) {
            afterDecryptionPassword = PasswordService.decryptAesPassword(dto.getNewPassword(), Constants.Normal.PASSWORD_KEY);
            encryptPassword = PasswordService.encryptPassword(afterDecryptionPassword, user.getSalt());
            user.setPassword(encryptPassword);
            this.dynamicSave(user);
        } else {
            throw new SystemException(CodeEnum.OLD_PASSWORD_ERROR);
        }
    }

    @Override
    public PageVO getByStatusAndSearchText(UserPageDTO pageDTO) {
        Pageable pageable = PageConverter.pageVOToPageable(pageDTO);
        Page<SystemUser> userPage;
        if (null == pageDTO.getStatus()) { // 是否存在status
            userPage = repository.findBySearchText(pageDTO.getSearchText(), pageable);
        } else {
            userPage = repository.findBySearchTextAndStatus(pageDTO.getSearchText(), pageDTO.getStatus(), pageable);
        }
        return PageConverter.pageToPageDTO(userPage);
    }

}
